package com.bootlever.framework.common.utils;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class ReflectUtils {

    private static List<String> types = Arrays.asList(new String[]{"java.lang.String","int","float","double","long","boolean","short","java.lang.Integer",
            "java.lang.Long","java.lang.Double","java.lang.Float","java.lang.Boolean","java.lang.Short"});

    private static List<String> booleans = Arrays.asList(new String[]{"java.lang.Boolean","boolean"});

    public static Object copySameProperties(Object source, Object target)
            throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        Class sourceClass = source.getClass();
        Class targetClass = target.getClass();
        Class clazz = sourceClass;
        //Field[] sourceFields = sourceClass.getDeclaredFields();
        List<Field> sourceFieldList = new ArrayList<Field>();
        while (clazz != null && !clazz.getName().equals("java,lang.Object")){
            sourceFieldList.addAll(Arrays.asList(clazz.getDeclaredFields()));
            clazz = clazz.getSuperclass();
        }
        Field[] targetFields = targetClass.getDeclaredFields();
        for (Field sourceField : sourceFieldList) {
            if (sourceField.isAccessible()) {
                //公有的不用
                continue;
            }
            if (Modifier.isStatic(sourceField.getModifiers())||Modifier.isPublic(sourceField.getModifiers())
                    ||Modifier.isFinal(sourceField.getModifiers())){
                continue;
            }
            String name = sourceField.getName();
            Class type = sourceField.getType();
            if (!types.contains(type.getName())) {
                continue;
            }
            String methodName = name.substring(0,1).toUpperCase() + name.substring(1);//属性首字母大写
            Method getMethod = null;
            try {
                if (booleans.contains(type.getName())){
                    getMethod = sourceClass.getMethod("is" + methodName);
                } else {
                    getMethod = sourceClass.getMethod("get" + methodName);
                }
            }catch (Exception e) {
                //没有get方法，应该是常量，不用赋值
                e.printStackTrace();
                continue;
            }
            Object value = getMethod.invoke(source);
            for (Field targetField : targetFields) {
                String targetName = targetField.getName();
                Class targetType = targetField.getType();
                if (targetName.equals(name) && type.getName().equals(targetType.getName())) {//type和名称都相同就赋值
                    Method setMethod = null;
                    try {
                        setMethod = targetClass.getMethod("set" + methodName, type);
                    }catch (Exception e) {
                        e.printStackTrace();//拿不到set方法
                        continue;
                    }
                    setMethod.invoke(target,value);
                    break;
                }
            }
        }
        return target;
    }
}
